/**
 * JAVACC DEMO 1.0
 */
package com.apache.ius;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.service.impl.redis.JedisSsoUtil;
import com.apache.cache.util.Validator;
import com.apache.client.InfoReleaseCoreCleint;
import com.apache.database.constant.SystemTools;
import com.apache.exception.BusinessException;
import com.apache.info.entity.PubMetadata;
import com.apache.ius.plugin.CustomMethodPlugin;
import com.apache.rpc.common.LoadRpcService;
import com.apache.tools.ConfigUtil;
import com.apache.uct.common.ToolsUtil;
import com.apache.uct.common.entity.Org;
import com.apache.uct.common.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * description:  生成动态sql
 *
 * @author dyhou 创建时间：2016-8-6
 */
public class IusSqlTools extends DymicSqlSuper {

	private Logger log = LoggerFactory.getLogger(getClass());

	public static final String SPANCENAME = "com.apache.ius.sql.DymicMapper";

	private static IusSqlTools instance;

	private IusSqlTools() {
	}

	public void init() {
		instance = this;
	}

	public static IusSqlTools getInstance() {
		if (null == instance) {
			instance = new IusSqlTools();
		}
		return instance;
	}

	/**
	 * description: 生成原生sql(无用了）
	 *
	 * @param vo 参数:exe_rules样例:exe_rules=pub.proId:[pro.proId],pub.proNo:[pro.proNo]<br>
	 * modelTypes样例:modelTypes=pro,pub,deal<br>
	 * @param exeType sql语句类型:insert:插入,update:修改,del删除
	 */
	public String cteageNativeSql(ParamsVo vo, String exeType) {
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		String execSql = "";
		//exeCustomPlugin(vo, "befor");
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			String str[] = modelTypes.split(",");
			for (int i = 0; i < str.length; i++) {//循环生成sql
				Map<String, String> res = IusClassUtil.getInstance().convert2Map(vo.getParams(), str[i]);
				String sql = "";
				if ("insert".equalsIgnoreCase(exeType)) {
					sql = createInsertSqlStr(res, str[i], vo);
				} else if ("update".equals(exeType)) {
					sql = createUpdateSqlStr(res, str[i], vo);
				}
				if (Validator.isNotNull(sql)) {
					execSql += sql + ";";
				}
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
		}
		log.info(execSql);
		//	exeCustomPlugin(vo, "after");
		return execSql;
	}

	/**
	 * description: 生成原生sql <br>
	 * modelTypes=i_pro,i_pub,i_deal或u_pro,u_pub,u_deal (i_表示插入,u_表示修改,d_表示删除)<br>
	 * 待处理字段样例:pub.proId=[pro.proId]<br>
	 * exe_rules样例:exe_rules=pub.proId:[pro.proId],pub.proNo:[pro.proNo]
	 *
	 * @param vo
	 */
	public String cteageNativeSql(ParamsVo vo) {
		//	exeCustomPlugin(vo, "befor");
		String execSql = "";
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			String str[] = modelTypes.split(",");
			try {
				for (int i = 0; i < str.length; i++) {//循环生成sql  (i_,u_,d_,ib_,ub_)
					//					Method method = NetSqlTools.class.getDeclaredMethod(str[i].substring(2) + "Sql", new Class[] {
					//							String.class, ParamsVo.class });
					//					String sql = String.valueOf(method.invoke(this, str[i], vo));
					//					if (Validator.isNotNull(sql)) {
					//						execSql += sql + ";";
					//					}
					execSql += dymicInsertSql(vo, str, i);
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new BusinessException(e.getMessage());
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
			log.info(execSql);
		}
		//	exeCustomPluginForAfter(vo, "after");
		return execSql;
	}

	/**
	 * description:  单表查询
	 */
	public String selectNativeSql(ParamsVo vo) {
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		String sortCode = String.valueOf(vo.getParams("sortCode"));

		try {

			String sql = "";
			//如果sortCode不为空，即走modelTypess_info,sortCode=pro_info的方式
			if (Validator.isNotNull(sortCode)) {
				Method method = IusSqlTools.class.getDeclaredMethod(modelTypes.substring(2) + "Sql",
						new Class[] { String.class, ParamsVo.class });
				sql = String.valueOf(method.invoke(this, modelTypes, vo));
			} else {
				//如果sortCode为空，则走modelTypes=s_TrpPro的方式
				String sign = "";
				if ("T".equalsIgnoreCase(String.valueOf(vo.getParams("_resultType")))) {
					sign = "@";
				}
				sql = getSelectMoreSqlStr(vo, modelTypes.split(","), sign);
			}
			log.info(sql);
			return sql;
		} catch (Exception e) {
			throw new BusinessException(e.getMessage());
		}
	}

	public String dymicNativeSql(ParamsVo vo) {
		String execSql = "";
		String modelTypes = String.valueOf(vo.getParams("modelTypes"));
		if (Validator.isNotNull(modelTypes)) {//是否有需要修改的类型
			exeCustomPlugin(vo, "befor");
			if (Validator.isNotNull(String.valueOf(vo.getParams(CustomMethodPlugin.pluginSql)))) {
				return String.valueOf(vo.getParams(CustomMethodPlugin.pluginSql));
			}
			String str[] = modelTypes.split(",");
			try {
				int count = str.length;
				if (modelTypes.startsWith("s_") && count > 1) {//多表联查
					execSql = getSelectMoreSqlStr(vo, str, "@");
				} else if (modelTypes.startsWith("sl_") || modelTypes.startsWith("sr_")
						|| modelTypes.startsWith("si_")) {
					execSql = getSelectJoinSqlStr(vo, str, "@");
				} else if (modelTypes.startsWith("s_") && count == 1) {//单表查询
					return selectNativeSql(vo);
				} else {
					for (int i = 0; i < str.length; i++) {//循环生成sql  (i_,u_,d_,ib_)
						execSql += dymicInsertSql(vo, str, i);
					}
				}
			} catch (Exception e) {
				throw new BusinessException(e.getMessage());
			}
		} else {
			execSql = String.valueOf(vo.getParams("execSql"));
		}
		log.info(execSql);
		return execSql;
	}

	private String dymicInsertSql(ParamsVo vo, String[] str, int i)
			throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		String prefix = str[i].substring(2);
		if (str[i].startsWith("ib_") || str[i].startsWith("ub_")) {
			prefix = str[i].substring(3);
		}
		String attr = ToolsUtil.getInstance().getValueByKey("custom-method.properties", "obj_" + prefix);
		String sql = "";
		if (Validator.isNull(attr)) {//判断是否动态表单
			attr = this.densgerSql(vo, prefix);
		}
		if (Validator.isNull(attr)) {
			Method method = IusSqlTools.class.getDeclaredMethod(str[i].substring(2) + "Sql",
					new Class[] { String.class, ParamsVo.class });
			sql = String.valueOf(method.invoke(this, str[i], vo));
		} else {
			String attrStr[] = attr.split(";");
			Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), prefix);

			sql = dymicSql(str[i], vo, attrStr[2], attrStr[1], prefix, params, attrStr[3]);

			if (prefix.equalsIgnoreCase("sysPluginGroup")) {//插件组合
				String rulesCode = String.valueOf(vo.getParams(prefix + ".rulesCode"));
				if (str[i].startsWith("d")) {
					delCacheInfo("sysPluginGroup.w_rulesId", String.valueOf(vo.getParams(prefix + ".rulesId")),
							"sysPluginGroup");
				} else {
					if (Validator.isNotNull(rulesCode)) {
						getPlugin().setPluginInfo(rulesCode, params.get("rulesName"));
					}
				}
			} else if (prefix.equalsIgnoreCase("sysPluginManager")) {//插件
				if (str[i].startsWith("d")) {
					delCacheInfo("sysPluginManager.w_infoId", String.valueOf(vo.getParams(prefix + ".infoId")),
							"sysPluginManager");
				} else {
					CustomMethodFactory.getInstance().setPlugins(params.get("pluginShortName"),
							params.get("pluginFullName"));
				}
			} else if (prefix.equalsIgnoreCase("sysParamManager")) {
				if (str[i].startsWith("d")) {
					delCacheInfo("sysParamManager.w_infoId", String.valueOf(vo.getParams(prefix + ".infoId")),
							"sysParamManager");
				}
			} else if (prefix.equalsIgnoreCase("trsRulesPro")) {//业务环节参数表-规则公式
				//                ResultEntity result = null;
				//                if (str[i].startsWith("d")) {//删除
				//                    Map<String, Object> pms = new HashMap<String, Object>();
				//                    pms.put("trsRulesPro.w_rulesProId", params.get("rulesProId"));
				//                    pms.put("modelTypes", "s_trsRulesPro");
				//                    pms.put("resultType", "objInfo");
				//                    pms.put("resultObjType", "obj");
				//                    pms.put("sysPass", ConfigUtil.getInstance().interfacePass());
				//                    result = LoadRpcService.service()
				//                            .doService("iusService", "dymicSql", "xml", pms, null);
				//                }
				//                setTrRulesProCache(str[i], params, result);
			}
		}
		if (Validator.isNotNull(sql)) {
			sql = sql + ";";
			String[] exsqlArry = sql.split(";");
			if(exsqlArry.length>1){
				String printSql = sql;
				printSql=printSql.replace(";", ";\n");
				printSql=printSql.substring(0, printSql.lastIndexOf("\n"));
				log.info("["+str[i]+"] Batch execution of SQL ：\n"+printSql);
			}else{
				log.info(sql);
			}
		}else{
			log.info(sql);
		}
		return sql;
	}

	/**
	 * 业务环节参数表-规则公式 缓存处理
	 *
	 */
	/*  private void setTrRulesProCache(final String type, final Map<String, String> params,
	        final ResultEntity result) {
	
	    new Thread(new Runnable() {
	
	        @Override
	        public void run() {
	            List caches = new ArrayList();
	            String cacheKey = "";
	            try {
	                if (type.startsWith("i") || type.startsWith("u")) {
	                    Map<String, String> paramKey = new HashMap();
	                    paramKey.put("type", params.get("constantType"));
	                    paramKey.put("status", params.get("constantStatus"));
	                    paramKey.put("proId", params.get("prodId"));
	                    paramKey.put("saleId", params.get("saleId"));
	                    cacheKey = ScriptEngineUtil.getInstance().getCacheKey(paramKey);
	                    List list = (List) LoadCacheFactory.getInstance().getCacheManager("")
	                            .getCacheObjectByKey(cacheKey);
	                    Map<String, String> cacheMap = new HashMap<>();
	                    cacheMap.put("rulesProId", params.get("rulesProId"));
	                    cacheMap.put("constantType", params.get("constantType"));
	                    cacheMap.put("constantStatus", params.get("constantStatus"));
	                    cacheMap.put("prodId", params.get("prodId"));
	                    cacheMap.put("saleId", params.get("saleId"));
	                    cacheMap.put("rulesNo", params.get("rulesNo"));
	                    cacheMap.put("orderNo", params.get("orderNo"));
	                    cacheMap.put("formulaName", params.get("formulaName"));
	                    cacheMap.put("formulaCal", params.get("formulaCal"));
	                    cacheMap.put("dealType", params.get("dealType"));
	                    cacheMap.put("paramNo", params.get("paramNo"));//参数值
	                    cacheMap.put("paramUnit", params.get("paramUnit"));//参数单位
	                    //cacheMap.put("formulaSrc", params.get("formulaSrc"));
	                    //cacheMap.put("formulaNo", params.get("formulaNo"));
	                    if (!Validator.isEmpty(list)) {
	                        if (type.startsWith("i")) {//新增
	                            caches.addAll(list);
	                        } else if (type.startsWith("u")) {//修改
	                            if (!Validator.isEmpty(list)) {
	                                Iterator<Map<String, String>> it = list.iterator();
	                                String id = params.get("rulesProId");
	                                while (it.hasNext()) {
	                                    Map<String, String> x = it.next();
	                                    if (!id.equals(x.get("rulesProId"))) {
	                                        list.add(x);
	                                    }
	                                }
	                            }
	                        }
	                    }
	                    caches.add(cacheMap);
	                } else {//删除
	                    if (null == result.getEntity()) {
	                        return;
	                    }
	                    String id = params.get("rulesProId");
	                    Map map = (Map) result.getEntity();
	                    Map<String, String> paramKey = new HashMap();
	                    paramKey.put("type", String.valueOf(map.get("constantType")));
	                    paramKey.put("status", String.valueOf(map.get("constantStatus")));
	                    paramKey.put("proId", StrUtil.doNull(String.valueOf(map.get("proId")), ""));
	                    paramKey.put("saleId",
	                            StrUtil.doNull(String.valueOf(map.get("saleId")), ""));
	                    cacheKey = ScriptEngineUtil.getInstance().getCacheKey(paramKey);
	                    List list = (List) LoadCacheFactory.getInstance().getCacheManager("")
	                            .getCacheObjectByKey(cacheKey);
	                    if (!Validator.isEmpty(list)) {
	                        Iterator<Map<String, String>> it = list.iterator();
	                        while (it.hasNext()) {
	                            Map<String, String> x = it.next();
	                            if (id.equals(x.get("rulesProId"))) {
	                                it.remove();
	                                break;
	                            }
	                        }
	                        caches.addAll(list);
	                    }
	                }
	                if (!caches.isEmpty()) {
	                    Collections.sort(caches, new Comparator<Map<String, String>>() {//数据排序
	
	                        public int compare(Map<String, String> o1, Map<String, String> o2) {
	                            return o1.get("orderNo").compareTo(o2.get("orderNo"));
	                        }
	                    });
	                    LoadCacheFactory.getInstance().getCacheManager("")
	                            .createCacheObject(cacheKey, caches);
	                }
	            } catch (Exception e) {
	
	            }
	        }
	    }).start();
	
	}
	*/
	///////////////////////以下拼装对象sql///////////////////////////////////////////
	protected String uctUserSql(String exeType, ParamsVo vo) {
		/***
		 * 不规范的表名与实体名（如UCT_USER表对应USER.java，应该是对应UctUser.java，需要这样写死
		 */
		vo.setParams(exeType + "_User", "uct_user");

		String result = reflection(exeType, vo, new User(), "user_id");
		return result;
	}

	protected String uctOrg(String exeType, ParamsVo vo) {
		vo.setParams(exeType + "_Org", "uct_org");
		String result = reflection(exeType, vo, new Org(), "org_id");
		return result;
	}

//	protected String tMemberSql(String exeType, ParamsVo vo) {
//		vo.setParams(exeType + "_Member", "t_member");//不规范的表名与实体名（理由同上），需要这样写死
//		String result = reflection(exeType, vo, new Member(), "member_id");
//		return result;
//	}

	protected String infoSql(String exeType, ParamsVo vo) {
		String sortCode = String.valueOf(vo.getParams("sortCode"));
		String sysName = String.valueOf(vo.getParams("datasource"));
		List<PubMetadata> list = InfoReleaseCoreCleint.getInstance().getMetadatas(sortCode, sysName);
		if (null == list)
			return "";
		Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), "info");
		String attrStr = "";
		String primaryKeyId = "info_id";
		for (PubMetadata pm : list) {
			if ("1".equals(pm.getDataRestrict())) {//处理主键
				primaryKeyId = pm.getDataShortName();
			}
			attrStr += pm.getDataAttr() + ",";
		}
		invokePlugin(exeType, vo, "info", params);
		String tableName = upperCharToUnderLine("pub_" + sortCode);
		String result = dymicSql(exeType, vo, primaryKeyId, attrStr, "info", params, tableName);
		return result;
	}

	private String reflection(String exeType, ParamsVo vo, Object obj, String primaryKeyId) {
		String result = "";
		String attrStr = getReflectAttr(obj);
		String modelType = exeType.substring(2);
		Map<String, String> params = IusClassUtil.getInstance().convert2Map(vo.getParams(), modelType);
		invokePlugin(exeType, vo, modelType, params);
		String tableName = upperCharToUnderLine(obj.getClass().getSimpleName());
		if (Validator.isNotNull(String.valueOf(vo.getParams(exeType + "_" + obj.getClass().getSimpleName())))) {
			tableName = String.valueOf(vo.getParams(exeType + "_" + obj.getClass().getSimpleName()));
		}
		result = dymicSql(exeType, vo, primaryKeyId, attrStr, modelType, params, tableName);
		return result;
	}

	private void invokePlugin(String exeType, ParamsVo vo, String modelType, Map<String, String> params) {
		String keys = String.valueOf(vo.getParams("sqlKeyId"));
		String invokeMethodKey = String.valueOf(vo.getParams("invokeMethodKey"));
		if (Validator.isNotNull(keys)) {
			if (Validator.isNull(invokeMethodKey))
				return;
			ParamsVo pvo = new ParamsVo();
			pvo.setParams(params);
			pvo.setParams("sqlKeyId", keys);
			pvo.setParams("plugin_exeType", modelType);
			pvo.setMethodKey("invokeMethodKey");
			Map<String, Object> map = (Map) getPlugin().doInvoke(pvo);
			if (!Validator.isEmpty(map) && !map.isEmpty()) {
				for (String key : map.keySet()) {
					params.put(key, String.valueOf(map.get(key)));
				}
				vo.setParams("invokeMethodKey", "");
				vo.setParams("sqlKeyId", "");
			}
		} else {
			if (Validator.isNull(invokeMethodKey))
				return;
			CustomMethodPlugin plugin = CustomMethodFactory.getInstance().getPluginByKey(invokeMethodKey);
			if (!Validator.isEmpty(plugin)) {
				if (exeType.startsWith("i_") || exeType.startsWith("u_") || exeType.startsWith("d_")) {
					vo.setParams("plugin_exeType", modelType);
					Map<String, Object> map = (Map) plugin.doInvoke(vo.getParams());
					if (!Validator.isEmpty(map)) {
						for (String key : map.keySet()) {
							params.put(key, String.valueOf(map.get(key)));
						}
					}
					vo.setParams("invokeMethodKey", "");
				}
			}
		}
	}

	/**
	 * description:  生成插入语句
	 */
	public String createInsertSqlStr(Map<String, String> params, String modelType, ParamsVo paramVo) {
		String result = "";
		return result;
	}

	/**
	 * description:  生成修改语句
	 */
	public String createUpdateSqlStr(Map<String, String> params, String modelType, ParamsVo paramVo) {
		String result = "";
		return result;
	}

	private void delCacheInfo(final String idKey, final String idValue, final String tabObj) {
		Map<String, Object> pms = new HashMap<String, Object>();
		pms.put(idKey, idValue);
		pms.put("modelTypes", "s_" + tabObj);
		pms.put("resultType", "objInfo");
		pms.put("resultObjType", "obj");
		pms.put("sysPass", ConfigUtil.getInstance().interfacePass());
		ResultEntity result = LoadRpcService.service().doService("iusService", "dymicSql", "xml", pms, null);
		Map objInfo = (Map) result.getEntity();
		if (null == objInfo)
			return;
		switch (tabObj) {
		case "sysPluginGroup"://组合插件
			getPlugin().setPluginInfo(String.valueOf(objInfo.get("rulesCode")), "");
			break;
		case "sysPluginManager"://单一插件
			CustomMethodFactory.getInstance().removePlugin(String.valueOf(objInfo.get("pluginShortName")));
			break;
		case "sysParamManager"://IUS参数
			String key = objInfo.get("formName") + "_" + objInfo.get("pageName");
			if (JedisSsoUtil.getInstance().isRedisCache()) {
				JedisSsoUtil.getInstance().delIusparamcache(key);
			} else {
				SystemTools.getInstance().getCache("iusparamcache").removeCacheObject(key);
			}
			break;
		}
	}

}
